using Microsoft.Practices.Unity;

namespace Synergy
{
	/// <summary>
	/// Service locator for dependency injection.
	/// </summary>
	/// <remarks>
	///		<list type="table">
	///			<listheader><term>Version</term><description>Description</description></listheader>
	///			<item>
	///				<term>1.0</term>
	///				<description>Initial version</description>
	///			</item>
	///		</list>
	/// </remarks>
	public abstract class ServiceLocatorBase : IServiceLocator
	{
		#region | Initialization |

		/// <summary>
		/// Initializes a new instance of the <see cref="ServiceLocatorBase"/> class.
		/// </summary>
		protected ServiceLocatorBase()
		{ }


		/// <summary>
		/// Initializes a new instance of the <see cref="ServiceLocatorBase"/> class.
		/// </summary>
		/// <param name="container">The container.</param>
		protected ServiceLocatorBase(IUnityContainer container)
		{
			InternalContainer = container;
		}

		#endregion


		#region | Properties |

		/// <summary>
		/// Gets or sets the container.
		/// </summary>
		/// <value>The container.</value>
		protected IUnityContainer InternalContainer { get; set; }


		/// <summary>
		/// Gets a value indicating whether this instance is initialized.
		/// </summary>
		/// <value><c>true</c> if this instance is initialized; otherwise, <c>false</c>.</value>
		public virtual bool IsInitialized
		{
			get { return (InternalContainer != null); }
		}

		#endregion


		#region | Methods [Public] |

		/// <summary>
		/// Initializes the service registry with the specified <paramref name="container"/>.
		/// </summary>
		/// <param name="container">The container.</param>
		public virtual void Initialize(IUnityContainer container)
		{
			InternalContainer = container;
		}


		/// <summary>
		/// Looks up the registered instance based on type <typeparamref name="T"/>.
		/// </summary>
		/// <typeparam name="T">The type to lookup.</typeparam>
		/// <remarks>
		///     Code analysis message CA1004 (Generic Methods Should Provide Type Parameter) is being suppressed here 
		///     because type-resolution must be explicit.
		/// </remarks>
		/// <returns>The registered instance of type <typeparamref name="T"/>.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
		public virtual T Lookup<T>()
		{
			// must be initialized (container is not null)
			if (!IsInitialized)
			{
				throw new ServiceLocatorNotInitializedException();
			}

			// resolve the instance
			return InternalContainer.Resolve<T>();
		}

		#endregion
	}
}